library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
library(car)
## Loading required package: carData
##
## Attaching package: 'car'
##
## The following object is masked from 'package:dplyr':
##
## recode
##
## The following object is masked from 'package:purrr':
##
## some
library(ggplot2)
library(lubridate)
data <- read_csv("study_tasks.csv")
## Rows: 49244 Columns: 35
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (9): TaskID, ActionID, distance, direction, complexity, zoomDirection,...
## dbl (22): UserID, main_translation_x, main_translation_y, main_translation_...
## lgl (3): rotateGlobeWhileDragging, oneHandedRotationGesture, moveGlobeWhil...
## dttm (1): Date
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
demographic <- read_csv("final_introductory.csv")
## Rows: 12 Columns: 8
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): Timestamp, Academic_level, Gender, Age_group, Exp_ARVR, Globe_usage...
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
positioning_NRG <- read_csv("final_positioning_NRG.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
positioning_RG <- read_csv("final_positioning_RG.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
positioning_preference <- read_csv("final_positioning_comparison.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Positioning_preference, Positioning_feedback
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rotation_OH <- read_csv("final_rotation_OH.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rotation_TH <- read_csv("final_rotation_TH.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rotation_preference <- read_csv("final_rotation_comparison.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Rotation_preference, Rotation_feedback
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
scale_MG <- read_csv("final_scale_MG.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
scale_NMG <- read_csv("final_scale_NMG.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Mentally_demanding, Physically_demanding
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
scale_preference <- read_csv("final_scale_comparison.csv")
## Rows: 12 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Timestamp, Scale_preference, Scale_feedback
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
combined_preference <- read_csv("final_outro_comparison.csv")
## Rows: 12 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): Timestamp, Combined_positioning_preference, Combined_rotation_prefe...
## dbl (1): UserID
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(data)
## spc_tbl_ [49,244 × 35] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:49244] 1 1 1 1 1 1 1 1 1 1 ...
## $ TaskID : chr [1:49244] "U1_P_RGFH_0001" "U1_P_RGFH_0001" "U1_P_RGFH_0001" "U1_P_RGFH_0001" ...
## $ ActionID : chr [1:49244] "F3432F60-93B4-41D3-A42A-81FC466E2A87" "F3432F60-93B4-41D3-A42A-81FC466E2A87" "F3432F60-93B4-41D3-A42A-81FC466E2A87" "F3432F60-93B4-41D3-A42A-81FC466E2A87" ...
## $ rotateGlobeWhileDragging: logi [1:49244] TRUE TRUE TRUE TRUE TRUE TRUE ...
## $ oneHandedRotationGesture: logi [1:49244] TRUE TRUE TRUE TRUE TRUE TRUE ...
## $ moveGlobeWhileScaling : logi [1:49244] FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ distance : chr [1:49244] "far" "far" "far" "far" ...
## $ direction : chr [1:49244] "horizontal" "horizontal" "horizontal" "horizontal" ...
## $ complexity : chr [1:49244] "simple" "simple" "simple" "simple" ...
## $ zoomDirection : chr [1:49244] "smallToLarge" "smallToLarge" "smallToLarge" "smallToLarge" ...
## $ Date : POSIXct[1:49244], format: "2025-04-23 05:27:13" "2025-04-23 05:27:13" ...
## $ Type : chr [1:49244] "positionTask" "positionTask" "positionTask" "positionTask" ...
## $ ActionStatus : chr [1:49244] "dragStart" "drag" "drag" "drag" ...
## $ main_translation_x : num [1:49244] -1.201 -1.201 -1.178 -0.949 -0.623 ...
## $ main_translation_y : num [1:49244] 1.86 1.86 1.86 1.85 1.78 ...
## $ main_translation_z : num [1:49244] -2.35 -2.35 -2.35 -2.43 -2.48 ...
## $ main_rotation_x : num [1:49244] 0 0 0 0 0 0 0 0 0 0 ...
## $ main_rotation_y : num [1:49244] 1 1 1 0.999 0.993 ...
## $ main_rotation_z : num [1:49244] 0 0 0 0 0 0 0 0 0 0 ...
## $ main_rotation_w : num [1:49244] 7.55e-08 8.24e-08 4.61e-03 5.19e-02 1.16e-01 ...
## $ main_scale_x : num [1:49244] 1 1 1 1 1 ...
## $ main_scale_y : num [1:49244] 1 1 1 1 1 ...
## $ main_scale_z : num [1:49244] 1 1 1 1 1 ...
## $ target_translation_x : num [1:49244] 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 ...
## $ target_translation_y : num [1:49244] 0.975 0.975 0.975 0.975 0.975 ...
## $ target_translation_z : num [1:49244] -2.25 -2.25 -2.25 -2.25 -2.25 -2.25 -2.25 -2.25 -2.25 -2.25 ...
## $ target_rotation_x : num [1:49244] 0 0 0 0 0 0 0 0 0 0 ...
## $ target_rotation_y : num [1:49244] 1 1 1 1 1 1 1 1 1 1 ...
## $ target_rotation_z : num [1:49244] 0 0 0 0 0 0 0 0 0 0 ...
## $ target_rotation_w : num [1:49244] 7.55e-08 7.55e-08 7.55e-08 7.55e-08 7.55e-08 ...
## $ target_scale_x : num [1:49244] 1 1 1 1 1 1 1 1 1 1 ...
## $ target_scale_y : num [1:49244] 1 1 1 1 1 1 1 1 1 1 ...
## $ target_scale_z : num [1:49244] 1 1 1 1 1 1 1 1 1 1 ...
## $ match_accuracy_result : num [1:49244] 0 0 0 0 0 0 0 0 0 0 ...
## $ status : chr [1:49244] "Attempt started" "Attempting" "Attempting" "Attempting" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. TaskID = col_character(),
## .. ActionID = col_character(),
## .. rotateGlobeWhileDragging = col_logical(),
## .. oneHandedRotationGesture = col_logical(),
## .. moveGlobeWhileScaling = col_logical(),
## .. distance = col_character(),
## .. direction = col_character(),
## .. complexity = col_character(),
## .. zoomDirection = col_character(),
## .. Date = col_datetime(format = ""),
## .. Type = col_character(),
## .. ActionStatus = col_character(),
## .. main_translation_x = col_double(),
## .. main_translation_y = col_double(),
## .. main_translation_z = col_double(),
## .. main_rotation_x = col_double(),
## .. main_rotation_y = col_double(),
## .. main_rotation_z = col_double(),
## .. main_rotation_w = col_double(),
## .. main_scale_x = col_double(),
## .. main_scale_y = col_double(),
## .. main_scale_z = col_double(),
## .. target_translation_x = col_double(),
## .. target_translation_y = col_double(),
## .. target_translation_z = col_double(),
## .. target_rotation_x = col_double(),
## .. target_rotation_y = col_double(),
## .. target_rotation_z = col_double(),
## .. target_rotation_w = col_double(),
## .. target_scale_x = col_double(),
## .. target_scale_y = col_double(),
## .. target_scale_z = col_double(),
## .. match_accuracy_result = col_double(),
## .. status = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(data)
## UserID TaskID ActionID
## Min. : 1.000 Length:49244 Length:49244
## 1st Qu.: 4.000 Class :character Class :character
## Median : 7.000 Mode :character Mode :character
## Mean : 6.741
## 3rd Qu.:10.000
## Max. :12.000
## rotateGlobeWhileDragging oneHandedRotationGesture moveGlobeWhileScaling
## Mode :logical Mode :logical Mode :logical
## FALSE:36803 FALSE:11933 FALSE:46552
## TRUE :12441 TRUE :37311 TRUE :2692
##
##
##
## distance direction complexity zoomDirection
## Length:49244 Length:49244 Length:49244 Length:49244
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Date Type ActionStatus
## Min. :2025-04-23 05:27:13.00 Length:49244 Length:49244
## 1st Qu.:2025-04-25 01:36:58.00 Class :character Class :character
## Median :2025-04-26 00:45:01.00 Mode :character Mode :character
## Mean :2025-04-27 21:46:53.98
## 3rd Qu.:2025-05-01 07:26:51.00
## Max. :2025-05-05 23:37:33.00
## main_translation_x main_translation_y main_translation_z main_rotation_x
## Min. :-7.099065 Min. :-0.3298 Min. :-3.487 Min. :-0.97540
## 1st Qu.:-0.400000 1st Qu.: 0.9000 1st Qu.:-1.921 1st Qu.:-0.03161
## Median :-0.004060 Median : 0.9000 Median :-1.500 Median : 0.00000
## Mean :-0.005048 Mean : 1.2326 Mean :-1.683 Mean :-0.03896
## 3rd Qu.: 0.400000 3rd Qu.: 1.5539 3rd Qu.:-1.500 3rd Qu.: 0.00000
## Max. : 3.256168 Max. : 3.8304 Max. : 5.006 Max. : 0.97834
## main_rotation_y main_rotation_z main_rotation_w main_scale_x
## Min. :-1.0000 Min. :-0.97710 Min. :-0.9997261 Min. :0.08431
## 1st Qu.:-0.2033 1st Qu.: 0.00000 1st Qu.: 0.0000001 1st Qu.:0.99989
## Median : 0.9601 Median : 0.00000 Median : 0.0626987 Median :1.00000
## Mean : 0.5003 Mean : 0.01287 Mean : 0.2756917 Mean :0.99575
## 3rd Qu.: 1.0000 3rd Qu.: 0.00000 3rd Qu.: 0.6346812 3rd Qu.:1.00002
## Max. : 1.0000 Max. : 0.98922 Max. : 0.9999814 Max. :7.69231
## main_scale_y main_scale_z target_translation_x target_translation_y
## Min. :0.08431 Min. :0.08431 Min. :-3.10000 Min. :0.613
## 1st Qu.:0.99994 1st Qu.:0.99990 1st Qu.:-0.40000 1st Qu.:0.900
## Median :1.00000 Median :1.00000 Median : 0.00000 Median :0.900
## Mean :0.99577 Mean :0.99576 Mean :-0.02449 Mean :1.245
## 3rd Qu.:1.00002 3rd Qu.:1.00002 3rd Qu.: 0.40000 3rd Qu.:1.773
## Max. :7.69231 Max. :7.69231 Max. : 2.33777 Max. :2.547
## target_translation_z target_rotation_x target_rotation_y target_rotation_z
## Min. :-3.3210 Min. :-0.3928 Min. :-0.6935 Min. :-0.21194
## 1st Qu.:-1.9598 1st Qu.:-0.3584 1st Qu.:-0.5655 1st Qu.: 0.00000
## Median :-1.5000 Median : 0.0000 Median : 1.0000 Median : 0.00000
## Mean :-1.6971 Mean :-0.1153 Mean : 0.3768 Mean :-0.01644
## 3rd Qu.:-1.5000 3rd Qu.: 0.0000 3rd Qu.: 1.0000 3rd Qu.: 0.00000
## Max. :-0.8953 Max. : 0.0000 Max. : 1.0000 Max. : 0.13795
## target_rotation_w target_scale_x target_scale_y target_scale_z
## Min. :-0.9761015 Min. :0.1700 Min. :0.1700 Min. :0.1700
## 1st Qu.: 0.0000001 1st Qu.:1.0000 1st Qu.:1.0000 1st Qu.:1.0000
## Median : 0.0000001 Median :1.0000 Median :1.0000 Median :1.0000
## Mean : 0.2914215 Mean :0.9946 Mean :0.9946 Mean :0.9946
## 3rd Qu.: 0.7119398 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. : 0.9807853 Max. :2.0000 Max. :2.0000 Max. :2.0000
## match_accuracy_result status
## Min. : 0.00000 Length:49244
## 1st Qu.: 0.00000 Class :character
## Median : 0.00000 Mode :character
## Mean : 0.03784
## 3rd Qu.: 0.00000
## Max. :22.31002
demographic$Timestamp <- trimws(demographic$Timestamp)
demographic$Timestamp <- dmy_hms(demographic$Timestamp, tz = "Australia/Melbourne")
## Warning: All formats failed to parse. No formats found.
str(demographic)
## spc_tbl_ [12 × 8] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : POSIXct[1:12], format: NA NA ...
## $ Academic_level : chr [1:12] "Graduate Student" "Graduate Student" "Graduate Student" "Graduate Student" ...
## $ Gender : chr [1:12] "Man" "Man" "Man" "Man" ...
## $ Age_group : chr [1:12] "30-40" "20-30" "30-40" "20-30" ...
## $ Exp_ARVR : chr [1:12] "I have no experience" "Familiar (5-20 hours experience)" "I have no experience" "Beginner (less than 5 hours experience)" ...
## $ Globe_usage_frequency: chr [1:12] "Once every few years" "Once every few years" "Once every few years" "A few times a month" ...
## $ Have_used_VisionPro : chr [1:12] "I have never used the Apple Vision Pro" "I have never used the Apple Vision Pro" "I have never used the Apple Vision Pro" "I have never used the Apple Vision Pro" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Academic_level = col_character(),
## .. Gender = col_character(),
## .. Age_group = col_character(),
## .. Exp_ARVR = col_character(),
## .. Globe_usage_frequency = col_character(),
## .. Have_used_VisionPro = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(demographic)
## UserID Timestamp Academic_level Gender
## Min. : 1.00 Min. :NA Length:12 Length:12
## 1st Qu.: 3.75 1st Qu.:NA Class :character Class :character
## Median : 6.50 Median :NA Mode :character Mode :character
## Mean : 6.50 Mean :NaN
## 3rd Qu.: 9.25 3rd Qu.:NA
## Max. :12.00 Max. :NA
## NA's :12
## Age_group Exp_ARVR Globe_usage_frequency
## Length:12 Length:12 Length:12
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
##
## Have_used_VisionPro
## Length:12
## Class :character
## Mode :character
##
##
##
##
str(positioning_NRG)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 15:38" "23/4/2025 16:47" "24/4/2025 11:24" "25/4/2025 11:34" ...
## $ Mentally_demanding : chr [1:12] "1. Very, very low mental effort" "2. Very low mental effort" "4. Rather low mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "0. No exertion" "2. Light" "3. Moderate" "0. No exertion" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(positioning_NRG)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(positioning_RG)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 15:33" "23/4/2025 16:49" "24/4/2025 11:20" "25/4/2025 11:37" ...
## $ Mentally_demanding : chr [1:12] "3. Low mental effort" "1. Very, very low mental effort" "5. Neither low nor high mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "2. Light" "1. Very light" "5. Difficult" "0. No exertion" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(positioning_RG)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(positioning_preference)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 15:50" "23/4/2025 16:56" "24/4/2025 11:27" "25/4/2025 11:42" ...
## $ Positioning_preference: chr [1:12] "Static orientation: The globe's orientation remains fixed while it moves." "Adaptive orientation: The globe rotates as it moves, so I always see the same side of the Earth." "Static orientation: The globe's orientation remains fixed while it moves." "Static orientation: The globe's orientation remains fixed while it moves." ...
## $ Positioning_feedback : chr [1:12] "I prefer the static orientation as it makes me feel more enjoyable and easy to move it. However, in relation t"| __truncated__ "Static orientation give me a little bit of nausea. And regarding the control, the x and y axis gesture is easy "| __truncated__ "Static is more intuitove because it only display 1 type of direction to control than adaptive. In order to rota"| __truncated__ "I like it when it static it is more dynamic and realistic like a globe should be, to move the globe I think it "| __truncated__ ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Positioning_preference = col_character(),
## .. Positioning_feedback = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(positioning_preference)
## UserID Timestamp Positioning_preference Positioning_feedback
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(rotation_OH)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:00" "23/4/2025 17:01" "24/4/2025 11:45" "25/4/2025 11:46" ...
## $ Mentally_demanding : chr [1:12] "2. Very low mental effort" "6. Rather high mental effort" "4. Rather low mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "1. Very light" "0. No exertion" "3. Moderate" "0. No exertion" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(rotation_OH)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(rotation_TH)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 15:57" "23/4/2025 17:04" "24/4/2025 11:35" "25/4/2025 11:53" ...
## $ Mentally_demanding : chr [1:12] "5. Neither low nor high mental effort" "3. Low mental effort" "6. Rather high mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "2. Light" "0. No exertion" "4. Somewhat difficult" "0.5. Noticable" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(rotation_TH)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(rotation_preference)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:04" "23/4/2025 17:09" "24/4/2025 11:48" "25/4/2025 11:55" ...
## $ Rotation_preference: chr [1:12] "One-handed rotation gesture" "Two-handed rotation gesture" "One-handed rotation gesture" "One-handed rotation gesture" ...
## $ Rotation_feedback : chr [1:12] "I feel more convenient to use one-handed rotation gesture because it is less confusing compared to two-handed r"| __truncated__ "I have more control with the two-handed rotation gesture, it feels more natural. But still feel limited In term"| __truncated__ "More fingers means more calorie burns. But it has limitation with the control, not sure how to solve or give ge"| __truncated__ "I like one handed better because I have more control to rotate the orientations as I like, as for the gestures "| __truncated__ ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Rotation_preference = col_character(),
## .. Rotation_feedback = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(rotation_preference)
## UserID Timestamp Rotation_preference Rotation_feedback
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(scale_MG)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:07" "23/4/2025 17:13" "24/4/2025 11:49" "25/4/2025 11:58" ...
## $ Mentally_demanding : chr [1:12] "1. Very, very low mental effort" "1. Very, very low mental effort" "2. Very low mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "0.5. Noticable" "0. No exertion" "1. Very light" "0. No exertion" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(scale_MG)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(scale_NMG)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:09" "23/4/2025 17:12" "24/4/2025 11:51" "25/4/2025 11:57" ...
## $ Mentally_demanding : chr [1:12] "1. Very, very low mental effort" "1. Very, very low mental effort" "2. Very low mental effort" "1. Very, very low mental effort" ...
## $ Physically_demanding: chr [1:12] "0.5. Noticable" "0. No exertion" "1. Very light" "0. No exertion" ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Mentally_demanding = col_character(),
## .. Physically_demanding = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(scale_NMG)
## UserID Timestamp Mentally_demanding Physically_demanding
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(scale_preference)
## spc_tbl_ [12 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:15" "23/4/2025 17:17" "24/4/2025 11:57" "25/4/2025 12:00" ...
## $ Scale_preference: chr [1:12] "Maintain distance to globe: The position of the globe moves while its size changes." "Maintain distance to globe: The position of the globe moves while its size changes." "Maintain distance to globe: The position of the globe moves while its size changes." "Maintain distance to globe: The position of the globe moves while its size changes." ...
## $ Scale_feedback : chr [1:12] "I prefer maintain globe position since it makes me easy to observe the globe closely and clearly, because I thi"| __truncated__ "For me personally I like to use the maintain distance to globe behaviour because its easier to see when observi"| __truncated__ "For the scope of this globe experiment, I prefer “maintain distance…”, because I do not think it is necessary t"| __truncated__ "I like the 2nd options better so we can observe the globe more detail, without being worry about the globe disa"| __truncated__ ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Scale_preference = col_character(),
## .. Scale_feedback = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(scale_preference)
## UserID Timestamp Scale_preference Scale_feedback
## Min. : 1.00 Length:12 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character Class :character
## Median : 6.50 Mode :character Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
str(combined_preference)
## spc_tbl_ [12 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ UserID : num [1:12] 1 2 3 4 5 6 7 8 9 10 ...
## $ Timestamp : chr [1:12] "23/4/2025 16:18" "23/4/2025 17:22" "24/4/2025 12:01" "25/4/2025 12:04" ...
## $ Combined_positioning_preference: chr [1:12] "Static orientation: The globe's orientation remains fixed while it moves." "Adaptive orientation: The globe rotates as it moves, so I always see the same side of the Earth." "Static orientation: The globe's orientation remains fixed while it moves." "Adaptive orientation: The globe rotates as it moves, so I always see the same side of the Earth." ...
## $ Combined_rotation_preference : chr [1:12] "One-handed rotation behaviour" "Two-handed rotation behaviour" "One-handed rotation behaviour" "One-handed rotation behaviour" ...
## $ Combined_scale_preference : chr [1:12] "Maintain globe position: The position of the globe remains unchanged, irrespective of size adjustments" "Maintain distance to globe: The position of the globe moves while its size changes." "Maintain distance to globe: The position of the globe moves while its size changes." "Maintain distance to globe: The position of the globe moves while its size changes." ...
## $ Combined_feedback : chr [1:12] "My preference remains the same even though they are combined." "More advance control could be implemented such as adding a feature when using 2 hands simultaneously to move th"| __truncated__ "My preferences remain the same if asked multiple behaviour of combination. I standstill like bamboo" "My feedbacks are still the same like the others sessions, but once we combined all the methods I like the adapt"| __truncated__ ...
## - attr(*, "spec")=
## .. cols(
## .. UserID = col_double(),
## .. Timestamp = col_character(),
## .. Combined_positioning_preference = col_character(),
## .. Combined_rotation_preference = col_character(),
## .. Combined_scale_preference = col_character(),
## .. Combined_feedback = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
summary(combined_preference)
## UserID Timestamp Combined_positioning_preference
## Min. : 1.00 Length:12 Length:12
## 1st Qu.: 3.75 Class :character Class :character
## Median : 6.50 Mode :character Mode :character
## Mean : 6.50
## 3rd Qu.: 9.25
## Max. :12.00
## Combined_rotation_preference Combined_scale_preference Combined_feedback
## Length:12 Length:12 Length:12
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
set.seed(123)
sample_data <- sample(data$match_accuracy_result, 5000)
shapiro.test(sample_data)
##
## Shapiro-Wilk normality test
##
## data: sample_data
## W = 0.16751, p-value < 2.2e-16
hist(data$match_accuracy_result, breaks = 100,
main = "Histogram (Zoomed)", xlab = "Accuracy",
col = "lightblue", xlim = c(-1, 100))
plot(density(data$match_accuracy_result),
main = "Density Plot (Zoomed)", xlab = "Accuracy",
col = "darkgreen", lwd = 2, xlim = c(-1, 5))
qqnorm(data$match_accuracy_result); qqline(data$match_accuracy_result, col = "red")
log_data <- log(data$match_accuracy_result + 1e-6)
hist(log_data, breaks = 100, main = "Log-transformed", col = "lightgreen")
qqnorm(log_data); qqline(log_data, col = "red")
sqrt_data <- sqrt(data$match_accuracy_result)
hist(sqrt_data, breaks = 100, main = "Sqrt-transformed", col = "lightcoral")
qqnorm(sqrt_data); qqline(sqrt_data, col = "red")
data %>%
filter(match_accuracy_result >= 2)
## # A tibble: 231 × 35
## UserID TaskID ActionID rotateGlobeWhileDrag…¹ oneHandedRotationGes…²
## <dbl> <chr> <chr> <lgl> <lgl>
## 1 1 U1_R_THS_0050 5A285236… FALSE FALSE
## 2 1 U1_R_THS_0050 5A285236… FALSE FALSE
## 3 1 U1_R_THS_0050 055111A2… FALSE FALSE
## 4 1 U1_R_THC_0053 81960F65… FALSE FALSE
## 5 1 U1_R_THC_0053 13EEFCAC… FALSE FALSE
## 6 1 U1_R_THC_0055 BE6677B0… FALSE FALSE
## 7 1 U1_R_THC_0055 4965AC4C… FALSE FALSE
## 8 1 U1_R_OHS_0060 622C20BA… FALSE TRUE
## 9 1 U1_R_OHC_0061 7C9339BB… FALSE TRUE
## 10 2 U2_P_RGFH_0029 948A9879… TRUE TRUE
## # ℹ 221 more rows
## # ℹ abbreviated names: ¹rotateGlobeWhileDragging, ²oneHandedRotationGesture
## # ℹ 30 more variables: moveGlobeWhileScaling <lgl>, distance <chr>,
## # direction <chr>, complexity <chr>, zoomDirection <chr>, Date <dttm>,
## # Type <chr>, ActionStatus <chr>, main_translation_x <dbl>,
## # main_translation_y <dbl>, main_translation_z <dbl>, main_rotation_x <dbl>,
## # main_rotation_y <dbl>, main_rotation_z <dbl>, main_rotation_w <dbl>, …
nrow(data)
## [1] 49244
z_scores <- scale(data$match_accuracy_result)
outliers_z <- which(abs(z_scores) > 3)
length(outliers_z)
## [1] 700
summary(data$match_accuracy_result[outliers_z])
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.8366 1.0854 1.5005 1.7609 2.1759 22.3100
Q1 <- quantile(data$match_accuracy_result, 0.25)
Q3 <- quantile(data$match_accuracy_result, 0.75)
IQR_val <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR_val
upper_bound <- Q3 + 1.5 * IQR_val
outliers_iqr <- data$match_accuracy_result < lower_bound | data$match_accuracy_result > upper_bound
sum(outliers_iqr)
## [1] 3261
summary(data$match_accuracy_result[outliers_iqr])
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000573 0.063969 0.299743 0.571416 0.716408 22.310022
boxplot(data$match_accuracy_result, main = "Boxplot of Accuracy", horizontal = TRUE)
hist(data$match_accuracy_result)
qqnorm(data$match_accuracy_result)
Total number of participants
length(unique(data$UserID))
## [1] 12
data %>%
filter(rotateGlobeWhileDragging == TRUE & Type == "positionTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0102 0.107 12441
data %>%
filter(rotateGlobeWhileDragging == FALSE & Type == "positionTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0131 0.119 11296
data %>%
filter(oneHandedRotationGesture == TRUE & Type == "rotationTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0808 0.351 7899
data %>%
filter(oneHandedRotationGesture == FALSE & Type == "rotationTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0654 0.308 11933
data %>%
filter(moveGlobeWhileScaling == TRUE & Type == "scaleTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0338 0.504 2692
data %>%
filter(moveGlobeWhileScaling == FALSE & Type == "scaleTask") %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
sd_accuracy = sd(match_accuracy_result, na.rm = TRUE),
count = n())
## # A tibble: 1 × 3
## mean_accuracy sd_accuracy count
## <dbl> <dbl> <int>
## 1 0.0264 0.325 2983
data %>%
group_by(Type) %>%
summarise(mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
median_completion = median(Date, na.rm = TRUE),
total_attempts = n()) %>%
arrange(desc(mean_accuracy))
## # A tibble: 3 × 4
## Type mean_accuracy median_completion total_attempts
## <chr> <dbl> <dttm> <int>
## 1 rotationTask 0.0715 2025-04-26 00:52:10 19832
## 2 scaleTask 0.0299 2025-04-26 01:08:28 5675
## 3 positionTask 0.0116 2025-04-26 00:29:32 23737
kruskal.test(match_accuracy_result ~ Type, data = data)
##
## Kruskal-Wallis rank sum test
##
## data: match_accuracy_result by Type
## Kruskal-Wallis chi-squared = 211.87, df = 2, p-value < 2.2e-16
data %>%
filter(Type == "positionTask") %>%
group_by(UserID, Type) %>%
summarise(
total_tasks = n_distinct(TaskID),
avg_accuracy = mean(match_accuracy_result, na.rm = TRUE),
used_rotating_globe = sum(rotateGlobeWhileDragging, na.rm = TRUE),
used_non_rotating_globe = sum(!rotateGlobeWhileDragging, na.rm = TRUE),
.groups = "drop"
) %>%
arrange(desc(avg_accuracy))
## # A tibble: 12 × 6
## UserID Type total_tasks avg_accuracy used_rotating_globe
## <dbl> <chr> <int> <dbl> <int>
## 1 6 positionTask 48 0.0240 990
## 2 1 positionTask 48 0.0207 1118
## 3 12 positionTask 48 0.0135 1032
## 4 9 positionTask 48 0.0124 1733
## 5 11 positionTask 48 0.0117 1220
## 6 4 positionTask 48 0.0113 757
## 7 2 positionTask 48 0.0113 437
## 8 3 positionTask 48 0.00892 1311
## 9 7 positionTask 48 0.00805 1553
## 10 10 positionTask 48 0.00617 983
## 11 5 positionTask 48 0.00391 638
## 12 8 positionTask 48 0.000478 669
## # ℹ 1 more variable: used_non_rotating_globe <int>
data %>%
filter(Type == "rotationTask") %>%
group_by(UserID, Type) %>%
summarise(
total_tasks = n_distinct(TaskID),
avg_accuracy = mean(match_accuracy_result, na.rm = TRUE),
used_one_hand = sum(oneHandedRotationGesture, na.rm = TRUE),
used_two_hand = sum(!oneHandedRotationGesture, na.rm = TRUE),
.groups = "drop"
) %>%
arrange(desc(avg_accuracy))
## # A tibble: 12 × 6
## UserID Type total_tasks avg_accuracy used_one_hand used_two_hand
## <dbl> <chr> <int> <dbl> <int> <int>
## 1 3 rotationTask 16 0.131 689 808
## 2 4 rotationTask 16 0.107 483 1014
## 3 5 rotationTask 16 0.0961 827 982
## 4 6 rotationTask 16 0.0930 483 1092
## 5 10 rotationTask 16 0.0802 1286 728
## 6 1 rotationTask 16 0.0686 441 630
## 7 8 rotationTask 16 0.0673 628 1114
## 8 9 rotationTask 16 0.0561 328 922
## 9 11 rotationTask 16 0.0551 479 1095
## 10 12 rotationTask 16 0.0462 571 609
## 11 2 rotationTask 16 0.0417 797 362
## 12 7 rotationTask 16 0.0374 887 2577
data %>%
filter(Type == "scaleTask") %>%
group_by(UserID, Type) %>%
summarise(
total_tasks = n_distinct(TaskID),
avg_accuracy = mean(match_accuracy_result, na.rm = TRUE),
used_moving_globe = sum(moveGlobeWhileScaling, na.rm = TRUE),
used_non_moving_globe = sum(!moveGlobeWhileScaling, na.rm = TRUE),
.groups = "drop"
) %>%
arrange(desc(avg_accuracy))
## # A tibble: 12 × 6
## UserID Type total_tasks avg_accuracy used_moving_globe used_non_moving_globe
## <dbl> <chr> <int> <dbl> <int> <int>
## 1 11 scal… 16 0.140 199 204
## 2 4 scal… 16 0.0594 139 161
## 3 3 scal… 16 0.0415 180 242
## 4 10 scal… 16 0.0294 185 306
## 5 12 scal… 16 0.0251 353 352
## 6 6 scal… 16 0.0216 215 358
## 7 5 scal… 16 0.0188 193 284
## 8 9 scal… 16 0.0182 133 153
## 9 1 scal… 16 0.0122 218 228
## 10 7 scal… 16 0.0102 198 136
## 11 2 scal… 16 0.00980 227 329
## 12 8 scal… 16 0.00718 452 230
## Attempt Distribution
## Bar chart - by Type
data %>%
group_by(UserID, Type) %>%
summarise(observations = n(), .groups = "drop") %>%
ggplot(aes(x = Type, y = observations, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~UserID, scales = "free_y") +
labs(title = "Number of Attempts per Task Type by User",
x = "User ID", y = "Number of Attempts", fill = "Task Type") +
theme_minimal() +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold"))
## Bar chart - by User
data %>%
group_by(UserID, Type) %>%
summarise(observations = n(), .groups = "drop") %>%
ggplot(aes(x = factor(UserID), y = observations, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(title = "Number of Attempts per Task Type by User",
x = "User ID", y = "Number of Attempts") +
theme_minimal() +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
strip.text = element_text(size = 10, face = "bold"),
plot.title = element_text(size = 14, face = "bold")
)
## Average Attempts per Task by User
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(attempts = n(), .groups = "drop") %>%
group_by(UserID, Type) %>%
summarise(avg_attempts = mean(attempts), .groups = "drop") %>%
ggplot(aes(x = Type, y = avg_attempts, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~UserID, scales = "free_y") +
labs(title = "Average Attempts per Task by User",
x = NULL, y = "Avg Attempts per Task", fill = "Task Type") +
theme_minimal() +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold"))
## Average Attempts per Task all users
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(attempts = n(), .groups = "drop") %>%
group_by(UserID, Type) %>%
summarise(avg_attempts = mean(attempts), .groups = "drop") %>%
ggplot(aes(x = Type, y = avg_attempts, fill = Type)) +
geom_col(position = "dodge") +
labs(title = "Average Attempts per Task all users",
x = NULL, y = "Avg Attempts per Task", fill = "Task Type") +
theme_minimal() +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold"))
## Average Attempts per User by Task
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(attempts = n(), .groups = "drop") %>%
group_by(UserID, Type) %>%
summarise(avg_attempts = mean(attempts), .groups = "drop") %>%
ggplot(aes(x = UserID, y = avg_attempts, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(title = "Average Attempts per User by Task",
x = NULL, y = "Avg Attempts per User", fill = "User") +
theme_minimal() +
theme(legend.position = "none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold"))
## Average Attempts per User by Task
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(attempts = n(), .groups = "drop") %>%
group_by(UserID, Type) %>%
summarise(avg_attempts = mean(attempts), .groups = "drop") %>%
ggplot(aes(x = UserID, y = avg_attempts, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(title = "Average Attempts per User by Task",
x = NULL, y = "Avg Attempts per User", fill = "User") +
theme_minimal() +
theme(legend.position = "none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold"))
# Completion time by time taken
# Completion time distribution
# Convert ISO timestamp to POSIXct
data_posixct <- data %>%
mutate(DateTime = ymd_hms(Date))
# Average Tasks Completion Time
data %>%
group_by(Type, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
group_by(Type) %>%
summarise(
avg_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = Type, y = avg_completion_time, fill = Type)) +
geom_col(position = "dodge") +
labs(
title = "Average Completion Time per User by Task",
x = NULL, y = "Avg Completion Time (mins)", fill = "User"
) +
theme_minimal() +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold")
)
# Average Total Type Completion Time
data %>%
group_by(Type, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
group_by(Type) %>%
summarise(
avg_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = Type, y = avg_completion_time, fill = Type)) +
geom_col(position = "dodge") +
labs(
title = "Average Completion Time per User by Task",
x = NULL, y = "Avg Completion Time (mins)", fill = "User"
) +
theme_minimal() +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold")
)
# Average Total Type Completion Time by Users
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
group_by(UserID, Type) %>%
summarise(
avg_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = UserID, y = avg_completion_time, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Completion Time per User by Task",
x = NULL, y = "Avg Completion Time (mins)", fill = "User"
) +
theme_minimal() +
theme(
legend.position = "none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold")
)
## Average Tasks Completion Time by Users
data %>%
group_by(UserID, Type, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
ggplot(aes(x = Type, y = completion_time, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~UserID, scales = "free_y") +
labs(
title = "Total Completion Time per Task Type by User",
x = "Task Type", y = "Total Time (mins)", fill = "Task Type"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold")
)
## Average Accuracy per Tasks by users
data %>%
group_by(UserID, Type) %>%
summarise(
avg_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = Type, y = avg_accuracy, fill = Type)) +
geom_col(position = "dodge") +
facet_wrap(~UserID, scales = "free_y") +
labs(
title = "Average Match Accuracy per Task Type by User",
x = "Task Type", y = "Average Match Accuracy", fill = "Task Type"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
axis.ticks.x = element_blank(),
strip.text = element_text(size = 8),
plot.title = element_text(size = 14, face = "bold")
)
# Accuracy distribution
ggplot(data, aes(x = match_accuracy_result)) +
geom_density(fill = "skyblue", alpha = 0.6) +
geom_rug(alpha = 0.1) +
facet_wrap(~Type, scales = "free_y") +
coord_cartesian(xlim = c(-0.05, 0.05)) +
scale_x_continuous(limits = c(-1, 1)) +
labs(title = "Distribution of Match Accuracy by Task Type",
x = "Match Accuracy",
y = "Density") +
theme_minimal() +
theme(strip.text = element_text(size = 10),
plot.title = element_text(face = "bold"))
## Warning: Removed 593 rows containing non-finite outside the scale range
## (`stat_density()`).
# Completion time by gender
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Gender) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Gender), y = mean_completion_time, fill = as.factor(Gender))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by gender
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Gender, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Gender), y = mean_accuracy, fill = as.factor(Gender))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal()
# Completion time by academic level
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Academic_level) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Academic_level), y = mean_completion_time, fill = as.factor(Academic_level))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by age academic level
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Academic_level, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Academic_level), y = mean_accuracy, fill = as.factor(Academic_level))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Completion time by age group
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Age_group) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Age_group), y = mean_completion_time, fill = as.factor(Age_group))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by age group
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Age_group, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Age_group), y = mean_accuracy, fill = as.factor(Age_group))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Completion time by previous AR/VR experience
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Exp_ARVR) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Exp_ARVR), y = mean_completion_time, fill = as.factor(Exp_ARVR))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by previous AR/VR experience
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Exp_ARVR, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Exp_ARVR), y = mean_accuracy, fill = as.factor(Exp_ARVR))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Completion time by previous globes Experience
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Globe_usage_frequency) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Globe_usage_frequency), y = mean_completion_time, fill = as.factor(Globe_usage_frequency))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by previous globes Experience
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Globe_usage_frequency, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Globe_usage_frequency), y = mean_accuracy, fill = as.factor(Globe_usage_frequency))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Completion time by previous Apple Vision Pro Experience
data %>%
group_by(UserID, TaskID) %>%
summarise(
completion_time = as.numeric(difftime(max(Date), min(Date), units = "mins")),
.groups = "drop"
) %>%
inner_join(demographic, by = "UserID") %>%
group_by(Have_used_VisionPro) %>%
summarise(
mean_completion_time = mean(completion_time, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Have_used_VisionPro), y = mean_completion_time, fill = as.factor(Have_used_VisionPro))) +
geom_col(position = "dodge") +
labs(
title = "Average Task Completion Time by Gender",
x = "Gender",
y = "Mean Completion Time (mins)"
) +
theme_minimal()
# Accuracy by previous Apple Vision Pro Experience
data %>%
inner_join(demographic, by = "UserID") %>%
group_by(Have_used_VisionPro, Type) %>%
summarise(
mean_accuracy = mean(match_accuracy_result, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(x = as.factor(Have_used_VisionPro), y = mean_accuracy, fill = as.factor(Have_used_VisionPro))) +
geom_col(position = "dodge") +
facet_wrap(~Type, scales = "free_y") +
labs(
title = "Average Match Accuracy by Gender and Type",
x = "Gender",
y = "Mean Accuracy",
fill = "Gender"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
library(scales)
##
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
##
## discard
## The following object is masked from 'package:readr':
##
## col_factor
# Positioning behaviour preference
# positioning_preference %>%
# mutate(
# ShortLabel = recode(Positioning_preference,
# "Static orientation: The globe's orientation remains fixed while it moves." = "Static Orientation",
# "Adaptive orientation: The globe rotates as it moves, so I always see the same side of the Earth." = "Adaptive Orientation",
# "I have no preference" = "No Preference"
# )
# ) %>%
# count(ShortLabel) %>%
# mutate(
# percent = n / sum(n),
# ncount = paste0(n, "\n", percent_format()(percent))
# ) %>%
# ggplot(aes(x = ShortLabel, y = n, fill = ShortLabel)) +
# geom_col(color = "white") + # Use geom_col() for the bar chart
# geom_text(aes(label = ncount), position = position_stack(vjust = 0.5), size = 4) + # Labels with count & percentage
# labs(
# title = "Distribution of Positioning Preferences",
# fill = "Preference"
# ) +
# theme_minimal() + # Use a minimal theme for a cleaner look
# theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotate x-axis labels for readability
#Rotating behaviour preference
rotation_preference %>%
count(Rotation_preference) %>%
mutate(
percent = n / sum(n),
ncount = paste0(n, "\n", percent_format()(percent))
) %>%
ggplot(aes(x = "", y = n, fill = Rotation_preference)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
geom_text(aes(label = ncount), position = position_stack(vjust = 0.5), size = 4) +
labs(
title = "Distribution of Rotation Preferences",
fill = "Preference"
) +
theme_void()
#Scaling behaviour preference
# scale_preference %>%
# mutate(
# ShortLabel = recode(Scale_preference,
# "Maintain distance to globe: The position of the globe moves while its size changes." = "Maintain Distance to Globe",
# "Maintain globe position: The position of the globe remains unchanged, irrespective of size adjustments" = "Maintain Globe Position",
# "I have no preference" = "No Preference"
# )
# ) %>%
# count(ShortLabel) %>%
# mutate(
# percent = n / sum(n),
# ncount = paste0(n, "\n", percent_format()(percent))
# ) %>%
# ggplot(aes(x = "", y = n, fill = ShortLabel)) +
# geom_col(width = 1, color = "white") +
# coord_polar(theta = "y") +
# geom_text(aes(label = ncount), position = position_stack(vjust = 0.5), size = 4) +
# labs(
# title = "Distribution of Scale Preferences",
# fill = "Preference"
# ) +
# theme_void()